﻿''' <summary>
''' Processes stament such as if an loops.
''' </summary>
''' <remarks></remarks>
Module Statements

    ''' <summary>
    ''' The typeof the last identifier processed.
    ''' </summary>
    ''' <remarks></remarks>
    Public CurType As String = ""

    'All the multiline statements are to be processed here


    ' Decides what type of statement it is and send it to the correct processor
    Sub StmtProcess(ByVal Stmt As String)
        If Stmt Like "if *" Then
            ProcessIf(Stmt)
        ElseIf Stmt Like "do until *" Then
            ProcessDU(Stmt)
        ElseIf Stmt Like "do while *" Then
            ProcessDW(Stmt)
        End If
    End Sub

    'EBNF for the statements in their own region
#Region "ifstmt EBNF"
    'if statement :-
    '<Instructions>;
    '...
    'if <ident>/<val> ==/!=/)/(/)=/(= <ident>/<val> then
    '[
    '<Instructions>:
    ']
    'elseif <ident>/<val> ==/!=/)/(/)=/(= <ident>/<val> then
    '[
    '<Instructions>:
    ']
    'else
    '[
    '<Instructions>:
    '];
    '<Instructions>;
    '...
    '
#End Region

#Region "do until stmt EBNF"

    'do until statement:-
    'do until ident>/<val> ==/!=/)/(/)=/(= <ident>/<val>
    '[
    '<Instructions>:
    '];

#End Region

    ''' <summary>
    ''' Processes a do until loop.
    ''' </summary>
    ''' <param name="DUStmt">The looping code.</param>
    ''' <remarks></remarks>
    Sub ProcessDU(ByVal DUStmt As String)
        DUStmt = DUStmt.Trim()
        Dim dusplit As String() = DUStmt.Split(New [Char]() {"["c, "]"c})

        Dim split As String() = dusplit(0).Split(New [Char]() {" "c})

        Dim identl As String = split(2)
        Dim identr As String = split(4)
        Dim op As String = split(3)

        op = op.Trim()

beginloop:

        Dim lval = StmtsGetVal(identl)
        Dim rval = StmtsGetVal(identr)

        Dim input As String = "if " & lval & " " & op & " " & rval
        Dim result As Boolean = EvalStmt(input)

        If result = True Then
            GoTo endloop
        ElseIf result = False Then
            StmtsExec(dusplit(1))
            GoTo beginloop
        End If
endloop:
    End Sub

    ''' <summary>
    ''' Processes a do while loop.
    ''' </summary>
    ''' <param name="DWStmt">The looping code.</param>
    ''' <remarks></remarks>
    Sub ProcessDW(ByVal DWStmt As String)
        DWStmt = DWStmt.Trim()
        Dim dwsplit As String() = DWStmt.Split(New [Char]() {"["c, "]"c})

        Dim split As String() = dwsplit(0).Split(New [Char]() {" "c})

        Dim identl As String = split(2)
        Dim identr As String = split(4)
        Dim op As String = split(3)

        op = op.Trim()

beginloop:

        Dim lval = StmtsGetVal(identl)
        Dim rval = StmtsGetVal(identr)

        Dim input As String = "if " & lval & " " & op & " " & rval
        Dim result As Boolean = EvalStmt(input)

        If result = True Then
            StmtsExec(dwsplit(1))
            GoTo beginloop
        ElseIf result = False Then
            GoTo endloop
        End If
endloop:
    End Sub

    ''' <summary>
    ''' Processes an if then else dtatement.
    ''' </summary>
    ''' <param name="IfStmt">The if the else statement to process.</param>
    ''' <remarks></remarks>
    Sub ProcessIf(ByVal IfStmt As String)
        IfStmt = IfStmt.Trim()
        Dim ifsplit As String() = IfStmt.Split(New [Char]() {"["c, "]"c})

        Dim finalnode As Integer = ifsplit.Length - 3

        Dim id As Integer = -1

        Do Until id = finalnode
            If id = -1 Then
                id = id + 1
            Else
                id = id + 2
            End If

            If ifsplit(id) Like "if *" Or ifsplit(id) Like "elseif *" Then
                Dim ans As Boolean = EvalStmt(ifsplit(id))
                If ans = True Then
                    id = id + 1
                    StmtsExec(ifsplit(id))
                    GoTo endquest
                End If
            ElseIf ifsplit(id) Like "elseif" = False And ifsplit(id) Like "else" = True Then
                id = id + 1
                StmtsExec(ifsplit(id))
                GoTo endquest
            End If
        Loop

endquest:

    End Sub

    ''' <summary>
    ''' Evaluates a mini expression with an operator in between (if operators).
    ''' </summary>
    ''' <param name="stmt">The statement to process.</param>
    ''' <returns>True or False accordingly.</returns>
    ''' <remarks></remarks>
    Function EvalStmt(ByVal stmt As String) As Boolean

        Dim stmtsplit As String() = stmt.Split(New [Char]() {" "c})

        Dim i As Integer = 0
        Dim len As Integer = stmtsplit.Length - 1

        Dim Found As Boolean = False
        Dim opi As Integer = 0

        Do Until Found = True

            i = i + 1

            stmtsplit(i).Trim()

            If stmtsplit(i).Trim() = "==" Or stmtsplit(i).Trim() = "!=" _
            Or stmtsplit(i).Trim() = ")" Or stmtsplit(i).Trim() = "!(" _
            Or stmtsplit(i).Trim() = "(" Or stmtsplit(i).Trim() = "!)" _
            Or stmtsplit(i).Trim() = ")=" Or stmtsplit(i).Trim() = "(=" _
            Or stmtsplit(i).Trim() = "!)=" Or stmtsplit(i).Trim() = "!(=" _
            Or stmtsplit(i).Trim() = "like" Or stmtsplit(i).Trim() = "!like" Then

                opi = i
                Found = True

            End If

        Loop

        Dim lexpr As String = ""
        Dim rexpr As String = ""

        i = 0

        Do Until i = opi - 1
            i = i + 1
            lexpr = lexpr & stmtsplit(i).Trim() & " "
        Loop

        i = i + 1

        Dim endl As Integer

        If stmtsplit(len).Trim() = "then" Then
            endl = len - 1
        Else
            endl = len
        End If

        Do Until i = endl
            i = i + 1
            rexpr = rexpr & stmtsplit(i).Trim() & " "
        Loop


        Dim identl As String = lexpr.Trim()
        Dim identr As String = rexpr.Trim()
        Dim op As String = stmtsplit(opi)

        identl = StmtsGetVal(identl.Trim())
        identr = StmtsGetVal(identr.Trim())

        op = op.Trim()

        If op = "==" Then
            If CStr(identl) = CStr(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "!=" Then
            If CStr(identl) <> CStr(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = ")" Or op = "!(" Then
            If CDbl(identl) > CDbl(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "(" Or op = "!)" Then
            If CDbl(identl) < CDbl(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = ")=" Then
            If CDbl(identl) >= CDbl(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "(=" Then
            If CDbl(identl) <= CDbl(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "!)=" Then
            If CDbl(identl) >= CDbl(identr) = False Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "!(=" Then
            If CDbl(identl) <= CDbl(identr) = False Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "like" Then
            If CStr(identl) Like CStr(identr) Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        ElseIf op = "!like" Then
            If CStr(identl) Like CStr(identr) = False Then
                EvalStmt = True
            Else
                EvalStmt = False
            End If
        End If

        Return EvalStmt
    End Function

    ''' <summary>
    ''' Used by this module and other functions to returmn the value of an identifier etc.
    ''' </summary>
    ''' <param name="ident">The particle to get the value of.</param>
    ''' <returns>The value of the particle input.</returns>
    ''' <remarks></remarks>
    Function StmtsGetVal(ByVal ident As String) As String
        Dim output As String = ""

        ident = ident.Trim()

        If ident Like "[A-Z]*" Or ident Like "[a-z]*" Or ident Like "[A-Z]" Or ident Like "[a-z]" Or ident.Contains("'") Or ident.Contains(" + ") _
        Or ident.Contains(" - ") Or ident.Contains(" * ") Or ident.Contains(" / ") Then
            If ident.Contains("'") Then
                Basic.EvalStr(ident)
                output = Basic.Strs
                CurType = "string"
            ElseIf ident.Contains("'") = False Then
                If ident.Contains(" * ") = True Or ident.Contains(" / ") = True _
                Or ident.Contains(" - ") = True Or ident.Contains(" + ") = True _
                Or ident.Contains("Sqrt|") = True And ident.Contains("'") = False _
                Or ident.Contains("Pi|") = True Then

                    Math.MathExpr(ident)
                    output = Math.Ans
                    CurType = "double"

                ElseIf ident.Trim() = "true" Or ident.Trim() = "True" Then
                    output = "True"
                    CurType = "boolean"
                ElseIf ident.Trim() = "false" Or ident.Trim() = "False" Then
                    output = "False"
                    CurType = "boolean"
                Else
                    output = GetVal(ident)
                    CurType = GetTyp(ident)
                End If
            End If
        ElseIf ident Like "[A-Z]*" = False And ident Like "[a-z]*" = False And ident Like "[A-Z]" = False And ident Like "[a-z]" = False Then
            ident = CDbl(ident)
            output = ident
            CurType = "double"
        End If

        Return output
    End Function

    ''' <summary>
    ''' Executes the part off the statement that conforms to the first true part of the statement.
    ''' </summary>
    ''' <param name="Instructions">The code to execute.</param>
    ''' <remarks></remarks>
    Sub StmtsExec(ByVal Instructions As String)

        Dim words As String = Instructions
        Dim split As String() = words.Split(New [Char]() {":"c})

        Dim s As String
        For Each s In split
            Executor.Process(s)
        Next
    End Sub

End Module
